﻿package br.com.programatech.asfinance{
	/**
	 * Black & Scholes é o método mais frequentemente empregado no mercado de 
	 * ações para calcular o preço justo de um derivativo. 
	 * Trata-se de uma equação usada no mundo todo e presente em praticamente 
	 * todos os softwares, livros e manuais que tratam de derivativos, além 
	 * de ser usada por grandes, pequenas e médias instituições financeiras como 
	 * critério para arbitrar preços. 
	 * */
	public class BlackScholes{
		public static function blackScholes(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number, d2:Number, value : Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			d2 = d1 - (Vol*Math.sqrt(T));
			value = S * normalCDF(d1) - X * Math.exp(-r*T)*normalCDF(d2);
			return value;
		}
		
		public static function delta(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			return normalCDF(d1);
		}
		
		public static function gamma(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			return (normalPDF(d1)/(S*Vol*Math.sqrt(T)));
		}		
		
		public static function vega(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			return (S * normalPDF(d1) * Math.sqrt(T));
		}
		
		public static function theta(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number, d2:Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			d2 = d1 - (Vol*Math.sqrt(T));
			return (-((S * normalPDF(d1) * Vol) /(2 * Math.sqrt(T)))-(r*X*Math.exp(-r*T)*normalCDF(d2)));
		}
		
		public static function rho(S:Number, X:Number, Vol:Number, r:Number, T:Number):Number{
			var d1:Number, d2:Number;
			d1 = ((Math.log(S / X) + (r + Math.pow(Vol,2)/2)*T)) / (Vol*Math.sqrt(T));
			d2 = d1 - (Vol*Math.sqrt(T));
			return X*T*Math.exp(-r*T)*normalCDF(d2);
		}
		
		public static function normalPDF(z:Number):Number{
			return (Math.exp(-Math.pow(z,2)/2) / Math.sqrt(2*Math.PI));
			
		}
		public static function normalCDF(z:Number):Number{
			var c1:Number, c2:Number, c3:Number, c4:Number, c5:Number, c6:Number, w:Number, y1:Number;
	   		c1 = 2.506628;
    		c2 = 0.3193815;
		    c3 = -0.3565638;
    		c4 = 1.7814779;
		    c5 = -1.821256;
		    c6 = 1.3302744;
		    if(z > 0 || z == 0) w = 1;
		    else w = -1;
		    y1 = 1 / (1 + 0.2316419 * w * z);
    		return 0.5 + w * (0.5 - (Math.exp(-z * z / 2) / c1) * (y1 * (c2 + y1 * (c3 + y1 * (c4 + y1 * (c5 + y1 * c6))))));
		}
	}
}